--[[

    Filename:	auxstr.lua

    Programmer:	aesiot

    Remark:

--]]

local auxstr = { _VERSION = "1.0" }

--------------------------------------------------------------------------------

function auxstr.is_alnum( c )

	local n = ( "integer" == math.type( c ) and c ) or c:byte()

	return ( n > 47 and n < 58 ) or ( n > 64 and n < 91 ) or ( n > 96 and n < 123 )
end

--------------------------------------------------------------------------------

function auxstr.is_alpha( c )

	local n = ( "integer" == math.type( c ) and c ) or c:byte()

	return ( n > 64 and n < 91 ) or ( n > 96 and n < 123 )
end

--------------------------------------------------------------------------------

function auxstr.is_cntrl( c )

	local n = ( "integer" == math.type( c ) and c ) or c:byte()

	return n < 32 or n > 127
end

--------------------------------------------------------------------------------

function auxstr.is_digit( c )

	local n = ( "integer" == math.type( c ) and c ) or c:byte()

	return n > 47 and n < 58
end

--------------------------------------------------------------------------------

function auxstr.is_lower( c )

	local n = ( "integer" == math.type( c ) and c ) or c:byte()

	return n > 96 and n < 123
end

--------------------------------------------------------------------------------

function auxstr.is_print( c )

	local n = ( "integer" == math.type( c ) and c ) or c:byte()

	return n > 31 and n < 127
end

--------------------------------------------------------------------------------

function auxstr.is_space( c )

	local n = ( "integer" == math.type( c ) and c ) or c:byte()

	return ( n > 8 and n < 14 ) or 32 == n
end

--------------------------------------------------------------------------------

function auxstr.is_upper( c )

	local n = ( "integer" == math.type( c ) and c ) or c:byte()

	return n > 64 and n < 91
end

--------------------------------------------------------------------------------

function auxstr.is_hexadecimal( c )

	local n = ( "integer" == math.type( c ) and c ) or c:byte()

	return ( n > 47 and n < 58 ) or ( n > 64 and n < 71 ) or ( n > 96 and n < 103 )
end

--------------------------------------------------------------------------------

function auxstr.pairs( str, pos, num )

	if nil == pos or pos < 1 then

		pos = 1
	end

	if nil == num or num < 1 then

		num = 1
	end

	local fn = function( len, idx )

		if idx > len then

			return nil
		end

		if idx + num > len then

			num = len - idx + 1
		end

		return idx + num, string.sub( str, idx, idx + num - 1 )
	end

	return fn, #str, pos
end

--------------------------------------------------------------------------------

function auxstr.split( s, pattern )

	local r = {}

	for x in string.gmatch( s or "", pattern or "[^.\\/]*" ) do

		table.insert( r, x )
	end

	return r
end

--------------------------------------------------------------------------------

function auxstr.to_hexstr( value, space )

	if "string" ~= type( value ) then

		return ""
	end

	local result = ""

	if #value > 0 then

		local format = "%02X"

		result = string.format( format, value:byte( 1 ) )

		if "string" == type( space ) then

			format = space .. format
		end

		for i = 2, #value, 1 do

			result = result .. string.format( format, value:byte( i ) )
		end
	end

	return result
end

--------------------------------------------------------------------------------

function auxstr.from_hexstr( value )

	if "string" ~= type( value ) then

		return ""
	end

	local c = 0

	local count = 1

	local result = ""

	for i = 1, #value, 1 do

		local n = value:byte( i, i )

		if auxstr.is_hexadecimal( n ) then

			if count % 2 == 1 then

				c = ( auxstr.is_digit( n ) and n - 48 ) or ( auxstr.is_upper( n ) and n - 65 + 10 ) or n - 97 + 10
			else

				c = ( c << 4 ) | ( ( auxstr.is_digit( n ) and n - 48 ) or ( auxstr.is_upper( n ) and n - 65 + 10 ) or n - 97 + 10 )

				result = result .. string.char( c )
			end

			count = count + 1
		end
	end

	return result
end

--------------------------------------------------------------------------------

function auxstr.lines( s, mode )

	return function( len, idx )

		if idx > len then

			return nil
		end

		for i = idx, len do

			local c = string.byte( s, i )

			if 13 == c then

				local n = 1

				if i + 1 <= len and 10 == string.byte( s, i + 1 ) then

					i = i + 1
					n = n + 1
				end

				return i + 1, string.sub( s, idx, i - ( ( mode and n ) or 0 ) )

			elseif 10 == c then

				return i + 1, string.sub( s, idx, i - ( ( mode and 1 ) or 0 ) )
			end
		end

		return len + 1, string.sub( s, idx, len )

	end, #s, 1
end

--------------------------------------------------------------------------------

function auxstr.trim( s )

	local i = 1

	local j = #s

	while i <= j do

		if 32 ~= string.byte( s, i ) then

			break
		end

		i = i + 1
	end

	while j >= i do

		if 32 ~= string.byte( s, j ) then

			break
		end

		j = j - 1
	end

	return string.sub( s, i, j )
end

--------------------------------------------------------------------------------

function auxstr.read_line( s, idx, mode )

	local len = #s

	if nil == idx then

		idx = 1
	end

	if idx > len then

		return nil, len + 1
	end

	for i = idx, len do

		local c = string.byte( s, i )

		if 13 == c then

			local n = 1

			if i + 1 <= len and 10 == string.byte( s, i + 1 ) then

				i = i + 1
				n = n + 1
			end

			return string.sub( s, idx, i - ( ( mode and n ) or 0 ) ), i + 1

		elseif 10 == c then

			return string.sub( s, idx, i - ( ( mode and 1 ) or 0 ) ), i + 1
		end
	end

	return string.sub( s, idx, len ), len + 1
end

--------------------------------------------------------------------------------

return auxstr
